#define __host__
#define __device__
#include <vector_types.h>

#include <algorithm/analytical_model/algorithm/cuda/ShadowBlockCalculator.cuh>
#include <algorithm/analytical_model/algorithm/cuda/grid/RectangleGrid.cuh>
#include <algorithm/analytical_model/algorithm/cuda/inter_op/ShadowBlockCalculator.h>
#include <algorithm/analytical_model/algorithm/cuda/inter_op/grid/RectangleGrid.h>
#include <utils/Utils.h>

#include <bit>
#include <memory>

using namespace solar::cuda::inter_op;

ShadowBlockCalculator::ShadowBlockCalculator()
{
    this->delegate_ptr_ = std::make_shared<solar::cuda::ShadowBlockCalculator>();
}

void ShadowBlockCalculator::calculate() const { this->delegate_ptr_->calculate(); }

void ShadowBlockCalculator::init(std::vector<Float3>& input_vertices) const
{
    this->delegate_ptr_->init(input_vertices);
}

auto ShadowBlockCalculator::getResult() const -> Float4*
{
    return std::bit_cast<Float4*>(this->delegate_ptr_->d_sb_result_);
}

auto ShadowBlockCalculator::getMicroHeliostatShadowBlock() const -> bool*
{
    return this->delegate_ptr_->d_microhelio_;
}

auto ShadowBlockCalculator::getMicroHeliostatShadowBlockPerRow() const -> bool*
{
    return this->delegate_ptr_->d_microhelio_per_row_;
}

void ShadowBlockCalculator::setHelioRowCol(const Int2& row_col) const
{
    this->delegate_ptr_->setHelioRowCol(std::bit_cast<int2>(row_col));
}

void ShadowBlockCalculator::setGrid(RectangleGrid* grid) const
{
    auto grid_ptr = std::dynamic_pointer_cast<solar::cuda::RectangleGrid>(grid->delegate_ptr_);
    this->delegate_ptr_->rectangle_grid_ = grid_ptr.get();
}

void ShadowBlockCalculator::setSunRayDirection(const Float3& direction) const
{
    structCopy(direction, this->delegate_ptr_->sun_direction_);
}

void ShadowBlockCalculator::calculateCenterBias(Float3* d_heliostat_positions) const
{
    this->delegate_ptr_->calculateCenterBias(std::bit_cast<float3*>(d_heliostat_positions));
}

auto ShadowBlockCalculator::getCudaStream() const -> cudaStream_t
{
    return this->delegate_ptr_->stream_;
}
